package de.fstyle.android.worldcanvas.fragments;

import java.util.Date;

import org.json.JSONException;
import org.json.JSONObject;

//import yuku.ambilwarna.AmbilWarnaDialog;
//import yuku.ambilwarna.AmbilWarnaDialog.OnAmbilWarnaListener;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.location.Location;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.Toast;

import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;

import de.fstyle.android.worldcanvas.BGColorTransitionDrawable;
import de.fstyle.android.worldcanvas.ColorUpdateRunnable;
import de.fstyle.android.worldcanvas.LocationWrapper;
import de.fstyle.android.worldcanvas.R;
import de.fstyle.android.worldcanvas.SendColorAsyncTask;
import de.fstyle.android.worldcanvas.SimpleLocationListener;
import de.fstyle.android.worldcanvas.model.ColorData;
import de.fstyle.android.worldcanvas.model.ObjectDescription;
import de.fstyle.android.worldcanvas.util.ColorUtils;

public class ColorFragment 
extends LocationFragment 
implements OnTouchListener, OnClickListener {

	public static final String LOG_TAG = "color_fragment";
	public static final int COLOR_CHANGE_INTERVAL = 1 * 1000; // in miliseconds
	public static final int COLOR_UPDATE_INTERVAL = 5 * 1000; // in miliseconds
	public static final int COLOR_UPDATE_RESUME_DELAY = 5 * 1000; // in miliseconds
	public static final int COLOR_UPDATE_INITIAL_DELAY = 0 * 1000; // in miliseconds
	public static final int DEFAULT_COLOR = Color.WHITE;
	public static final String INITIAL_COLOR_ARGUMENT = "initial.color";

	private SimpleLocationListener simpleLocationListener;
	private LocationWrapper locationWrapper = new LocationWrapper();
	private Thread colorThread = null;
	private ColorUpdateRunnable colorRunnable;
	private Integer currentColor = DEFAULT_COLOR;

	private ConnectivityManager connectivityManager;
	
//	private long down = -1L;
//	private int downX = -1;
//	private int downY = -1;

	@Override
	public View onCreateView(
			LayoutInflater inflater, 
			ViewGroup container,
			Bundle savedInstanceState) {
		

		View view = inflater.inflate(R.layout.fragment_color, container, false);
		
		// register on touch listener 
		view.setOnTouchListener(this);
//		view.setOnClickListener(this);
		
		return view;
	}
	
	public void setInternetAvailable(boolean isAvailable) {
		
		if (this.getView() == null) return;
		
		View textView = this.getView().findViewById(R.id.no_internet_connection);
		
		if (isAvailable) {
			textView.setVisibility(View.GONE);
		} else {
			textView.setVisibility(View.VISIBLE);
		}
	}
	
	public void setLocationAvailable(boolean isAvailable) {
		
		if (this.getView() == null) return;
		
		View textView = this.getView().findViewById(R.id.no_current_location);
		
		if (isAvailable) {
			textView.setVisibility(View.GONE);
		} else {
			textView.setVisibility(View.VISIBLE);
		}
	}	
	
	public void setColorAttached(boolean isAttached) {
		
		if (this.getView() == null) return;
		
		View textView = this.getView().findViewById(R.id.no_color_attached);
		
		if (isAttached) {
			textView.setVisibility(View.GONE);
		} else {
			textView.setVisibility(View.VISIBLE);
		}
	}
	
	@Override
	public void onViewCreated(View view, Bundle savedInstanceState) {
		super.onViewCreated(view, savedInstanceState);

		Bundle bundle = this.getArguments();
		if (bundle != null) {
			int color = this.getArguments().getInt(
					INITIAL_COLOR_ARGUMENT, 
					DEFAULT_COLOR);
			this.setCurrentColor(color);
		}
		
		this.startColorUpdate(COLOR_UPDATE_INITIAL_DELAY);
	}
	
	
	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);

		registerLocationListener();

		this.connectivityManager = (ConnectivityManager) 
				this.getActivity().getSystemService(
						Context.CONNECTIVITY_SERVICE);
		
		servicesConnected();
	}
	
	@Override
	public void onStart() {
		super.onStart();
	}
	
	@Override
	public void onPause() {
		super.onPause();
		
		Log.d(LOG_TAG, "pausing");
		
//		unregisterLocationListener();
		stopColorUpdate();
	}
	
	@Override
	public void onResume() {
		super.onResume();
		
		Log.d(LOG_TAG, "resuming");
		
//		registerLocationListener();
		
		startColorUpdate(COLOR_UPDATE_RESUME_DELAY);
	}
	
	@Override
	public void onConnected(Bundle dataBundle) {
		
		super.onConnected(dataBundle);
		
		Log.d(LOG_TAG, "Location: " + this.locationClient.getLastLocation());
		
		this.locationClient.requestLocationUpdates(
				LocationRequest.create().setInterval(0), 
				new LocationListener() {
			
			@Override
			public void onLocationChanged(Location location) {
				Log.d(LOG_TAG, "Location: " + location);
			}
		});
	}
	
	@SuppressLint("NewApi")
	@SuppressWarnings("deprecation")
	public void setCurrentColor(Integer color) {

		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

			ObjectAnimator colorFade = ObjectAnimator.ofObject(
					this.getView(), 
					"backgroundColor", 
					new ArgbEvaluator(),
					this.currentColor, 
					color);
			colorFade.setDuration(COLOR_CHANGE_INTERVAL);
			colorFade.start();

		} else {

			ColorDrawable layers[] = new ColorDrawable[2];
			layers[0] = new ColorDrawable(this.currentColor);
			layers[1] = new ColorDrawable(color);
			BGColorTransitionDrawable backgroundColorAnimation = 
					new BGColorTransitionDrawable(layers);
			this.getView().setBackgroundDrawable(
					backgroundColorAnimation);
			backgroundColorAnimation.startTransition(COLOR_CHANGE_INTERVAL);

		}

		Log.d(LOG_TAG, this.currentColor + " -> " + color);

		this.currentColor = color;
	}

	public boolean isOnline() {
		
		NetworkInfo networkInfo = 
				this.connectivityManager.getActiveNetworkInfo();
		
		return networkInfo != null && networkInfo.isConnected();
	}
	
	public void startColorUpdate(long delay) {
		
		Log.d(LOG_TAG, "starting color update");
		
		if (this.colorRunnable == null || !this.colorRunnable.isActive()) {
			this.colorRunnable = new ColorUpdateRunnable(
					this,
					this.locationWrapper,
					COLOR_UPDATE_INTERVAL,
					delay);
			this.colorThread = new Thread(this.colorRunnable);
			this.colorThread.start();
		}
	}
	
	public void stopColorUpdate() {
		
		Log.d(LOG_TAG, "stopping color update");
		
		if (this.colorRunnable != null) {
			this.colorRunnable.stop();
		}
	}

	public void unregisterLocationListener() {
		
		LocationManager locationManager = (LocationManager) 
				this.getActivity().getSystemService(Context.LOCATION_SERVICE);
		
		if (this.simpleLocationListener != null) {
			locationManager.removeUpdates(this.simpleLocationListener);
		}
	}
	
	public void registerLocationListener() {

		LocationManager locationManager = (LocationManager) 
				this.getActivity().getSystemService(Context.LOCATION_SERVICE);

		if (this.simpleLocationListener == null) {
			this.simpleLocationListener = 
					new SimpleLocationListener(this.locationWrapper);
		}

		long timeLimit = System.currentTimeMillis() - (30 * 60 * 1000);
		
		try {
			Location location = locationManager.getLastKnownLocation(
					LocationManager.GPS_PROVIDER);
			
			if (location != null && location.getTime() > timeLimit) {
				this.locationWrapper.setLocation(location);
			}
			
			locationManager.requestLocationUpdates(
					LocationManager.GPS_PROVIDER,
					0 * 1000, // milliseconds
					0, // meters
					simpleLocationListener);
		} catch (IllegalArgumentException e) {
			Log.d(LOG_TAG, "'gps' provider does not exist.");
		}

		try {
			
			Location location = locationManager.getLastKnownLocation(
					LocationManager.NETWORK_PROVIDER);
			Location reference = this.locationWrapper.getLocation();
			
			if (location != null 
					&& location.getTime() > timeLimit 
					&& (reference == null || location.getTime() > reference.getTime())) {
				this.locationWrapper.setLocation(location);
			}
			
			locationManager.requestLocationUpdates(
					LocationManager.NETWORK_PROVIDER, 
					0 * 1000, // milliseconds
					0, // meters
					simpleLocationListener);
		} catch (IllegalArgumentException e) {
			Log.d(LOG_TAG, "'network' provider does not exist.");
		}
	}
	
	@Override
	public boolean onTouch(View v, MotionEvent event) {

		Log.d(LOG_TAG, "COLOR - TOUCH: " +event.getAction());
		
		if (event.getAction() == MotionEvent.ACTION_UP) {
			
			long time = event.getEventTime() - event.getDownTime();
			Log.d(LOG_TAG, time + " DOWN");
			if (time > 250) {
				return false; 
			}

			// initialColor is the initially-selected color to be shown in the
			// rectangle on the left of the arrow.
			// for example, 0xff000000 is black, 0xff0000ff is blue. Please be
			// aware of the initial 0xff which is the alpha.

//			AmbilWarnaDialog dialog = new AmbilWarnaDialog(
//					this.getActivity(),
//					this.currentColor, 
//					new OnAmbilWarnaListener() {
//						@Override
//						public void onOk(AmbilWarnaDialog dialog, int color) {
//
//							Location location = 
//									ColorFragment.this.locationWrapper.getLocation();
//
//							if (location == null) {
//								new Handler(Looper.getMainLooper()).post(new Runnable() {
//									@Override
//									public void run() {
//										Toast toast = Toast.makeText(
//											ColorFragment.this.getActivity(),
//											"No location fix.\n"
//													+ "New color was not sent.\n"
//													+ "Try again later.",
//											Toast.LENGTH_LONG);
//										toast.show();
//									}
//								});
//							} else {
//
//								ColorData colorData = 
//										new ColorData(color, new Date());
//
//								try {
//									JSONObject jsonObject = ColorUtils.getJson(colorData);
//									ObjectDescription<?> objectDescription = 
//										new ObjectDescription<JSONObject>(
//											jsonObject, 
//											null, 
//											location);
//
//									Log.d(LOG_TAG, "Sending data in async task.");
//									new SendColorAsyncTask(ColorFragment.this)
//											.execute(objectDescription);
//
//									// TODO: maybe move this to SendColorAsyncTask so that the background does not change at all?
//									Log.d(LOG_TAG, "Changing background color.");
//									ColorFragment.this.setCurrentColor(color);
//									
//									// AlertDialog.Builder builder =
//									// new AlertDialog.Builder(
//									// MainActivity.this);
//									// builder.setMessage("Test: \n" +
//									// location.getLongitude() + "\n " +
//									// location.getLatitude());
//									// builder.create().show();
//
//								} catch (JSONException e) {
//									// should never happen, actually
//									Log.d(LOG_TAG, "JSON generation failed", e);
//								}
//							}
//						}
//
//						@Override
//						public void onCancel(AmbilWarnaDialog dialog) {
//							// cancel was selected by the user
//						}
//					});
//
//			dialog.show();

			return true;
		}
		
		return true;

	}

	@Override
	public void onClick(View v) {
		Log.d(LOG_TAG, "CLICK");
	}


}
